from captcha.models import CaptchaStore
from django.contrib.auth.password_validation import validate_password
from django.core.validators import EmailValidator
from django.utils import timezone
from rest_framework import serializers
from django.core.exceptions import ValidationError
from rest_framework.validators import UniqueValidator
from rest_framework_simplejwt.models import TokenUser

from utils.get_token import get_tokens_for_user
from .models import Article, ArticleKeyword, ArticleCategory, UserKeywordFocus
from django.contrib.auth.models import User
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer


# Serializers define the API representation.
class ArticleCategorySerializer(serializers.ModelSerializer):
    children = serializers.SerializerMethodField()

    def get_children(self, instance, level=1):
        # 递归获取子节点的序列化数据
        children = instance.get_children()
        serializer = self.__class__(children, many=True)
        return serializer.data

    def to_representation(self, instance):
        if instance.get_children().exists():
            return super().to_representation(instance)
        else:
            representation = super().to_representation(instance)
            representation.pop('children')  # 移除children属性
            return representation

    class Meta:
        model = ArticleCategory
        fields = ["id", "name", "children"]


class ArticleKeywordSerializer(serializers.HyperlinkedModelSerializer):
    category_count = serializers.SerializerMethodField()

    def get_category_count(self, obj):
        category_id = self.context.get('category_id')
        # 根据category_id和关键词obj筛选文章数量
        if category_id == "-1" or category_id is None:
            return obj.value
        else:
            return obj.article_set.filter(category=category_id).count()

    class Meta:
        model = ArticleKeyword
        fields = ['id', 'text', 'value', 'category_count']


class ArticleKeywordCreateOptionSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = ArticleKeyword
        fields = ['id']


class ArticleSerializer(serializers.HyperlinkedModelSerializer):
    keywords = ArticleKeywordSerializer(many=True)
    category = ArticleCategorySerializer(many=True)

    class Meta:
        model = Article
        fields = ['id', 'title', 'url', 'thumb', 'abstract', 'keywords', 'category',
                  'keyword_contents', 'public_time', 'author', 'article_source']


class UserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(style={'input_type': 'password'},
                                     write_only=True, required=True, )

    class Meta:
        model = User
        fields = ("id", "username", "email", "is_active", "password")


class UserRegSerializer(serializers.ModelSerializer):
    username = serializers.CharField(label="用户名", help_text="用户名", required=True, allow_blank=False,
                                     validators=[UniqueValidator(queryset=User.objects.all(), message="用户已经存在")])

    # write_only = True 表示接口将不返回该字段
    password = serializers.CharField(style={'input_type': 'password'},
                                     write_only=True, required=True, )
    password2 = serializers.CharField(style={'input_type': 'password'}, write_only=True, required=True,
                                      help_text="确认密码", label="确认密码", )
    email = serializers.CharField(label="邮箱", help_text="邮箱", required=True, allow_blank=False,
                                  validators=[UniqueValidator(queryset=User.objects.all(), message="邮箱已经存在"),
                                              EmailValidator(message="请输入有效的 Email 格式")
                                              ])


    def validate_password(self, value):
        try:
            validate_password(value)
        except ValidationError as e:
            # 自定义错误消息
            error_messages = {
                'password_too_common': '密码太常见了，请选择一个更强的密码。',
                'password_entirely_numeric': '密码不能完全由数字组成。',
                'password_too_short': '密码长度至少8位',
                # 添加其他自定义错误消息...
            }
            # 获取第一个错误消息
            error_key = e.error_list[0].code
            error_message = error_messages.get(error_key, str(e))
            raise serializers.ValidationError(error_message)

        return value

    def validate(self, attrs):

        if attrs['password'] != attrs['password2']:
            raise serializers.ValidationError(
                {"password": "密码不匹配，请检查密码是否正确"})
        # 登录成功返回token信息
        return attrs
        # return attrs

    def create(self, validated_data):
        user = User.objects.create(
            username=validated_data['username'],
            email=validated_data['email'],
        )

        user.set_password(validated_data['password'])
        user.is_active = True
        user.save()

        return user

    class Meta:
        model = User
        fields = ("id", "is_active", "username", "email", "password", "password2")


class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    captcha = serializers.CharField(max_length=4, required=True,
                                    trim_whitespace=True, min_length=1,
                                    error_messages={
                                        "max_length": "图片验证码仅允许4位",
                                        "min_length": "图片验证码仅允许1位",
                                        "required": "请输入图片验证码"
                                    }, help_text="图片验证码")
    imgcode_id = serializers.CharField(required=True, write_only=True,
                                       help_text="图片验证码id")

    @classmethod
    def get_token(cls, user):
        token = super(MyTokenObtainPairSerializer, cls).get_token(user)
        # 添加额外信息
        token['username'] = user.username
        return token

    def validate_captcha(self, captcha):
        # 验证码验证
        try:
            captcha = captcha.lower()
        except:
            raise serializers.ValidationError("验证码错误")
        img_code = CaptchaStore.objects.filter(
            id=int(self.initial_data['imgcode_id'])).first()
        if img_code is None:
            raise serializers.ValidationError("验证码不存在")
        if img_code and timezone.now() > img_code.expiration:
            raise serializers.ValidationError("验证码已过期")
        elif img_code.response != captcha:
            raise serializers.ValidationError("验证码错误")

        img_code.delete()


class UserKeywordFocusSerializer(serializers.ModelSerializer):
    # 这里应该走配置项 json 形式
    class Meta:
        model = UserKeywordFocus
        fields = ("id", "event", "config")


# TODO 需要将关键词的创建和关键词事件的创建分开
class UserKeywordFocusCreatedSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = UserKeywordFocus
        fields = ("id", "event", "user", "config")

    def create(self, validated_data):
        request_user = self.context['request'].user
        if isinstance(request_user, TokenUser):
            user = User.objects.get(id=request_user.id)  # Convert TokenUser to User object
        else:
            user = request_user
        validated_data['user'] = user
        return super().create(validated_data)
